package com.reebake.ideal.crypto.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.reebake.ideal.constants.CommonConstants;
import com.reebake.ideal.crypto.entity.SecretKeyEntity;
import com.reebake.ideal.crypto.core.SecretKeyService;
import com.reebake.ideal.crypto.exception.JwtVerifyFailureException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Collection;
import java.util.Date;
import java.util.Map;

/**
 * jwt工具类
 */
public class JwtUtil implements ApplicationContextAware {
    private static SecretKeyService secretKeyService;

    /**
     * 获取RSA密钥
     * @return
     */
    private static RSA getRsaKey() {
        SecretKeyEntity secretKeyEntity = secretKeyService.queryRsa();
        return SecureUtil.rsa(secretKeyEntity.getPrivateKey(), secretKeyEntity.getPublicKey());
    }

    /**
     * 加密
     * @param subject 主题
     * @param userId 用户编号
     * @param authorities 权限
     * @param expiresAt 到期时间
     * @return jwt票据
     */
    public static String encode(String subject, String userId, Collection<String> authorities, Date expiresAt) {
        Map<String, Object> headers = MapUtil.newHashMap();
        Date now = DateUtil.date();
        Map<String, Object> payload = MapUtil.newHashMap();
        payload.put(JWT.JWT_ID, IdUtil.fastSimpleUUID());
        payload.put(JWT.SUBJECT, subject);
        payload.put(JWT.ISSUER, "issuer");
        payload.put(JWT.ISSUED_AT, now);
        payload.put(JWT.AUDIENCE, "audi");
        payload.put(JWT.EXPIRES_AT, expiresAt);
        payload.put(CommonConstants.ATTRIBUTE_NAME_USER_ID, userId);
        payload.put(CommonConstants.ATTRIBUTE_NAME_AUTHORITIES, authorities);



        JWTSigner jwtSigner = JWTSignerUtil.rs512(getRsaKey().getPrivateKey());
        return JWTUtil.createToken(headers, payload, jwtSigner);
    }

    /**
     * 解密
     * @param token jwt票据
     * @return JWT实体
     */
    public static JWT decode(String token) {
        JWTSigner jwtSigner = JWTSignerUtil.rs512(getRsaKey().getPublicKey());
        if(!JWTUtil.verify(token, jwtSigner)) {
            throw new JwtVerifyFailureException();
        }

        JWT jwt = JWTUtil.parseToken(token);
        jwt.setSigner(jwtSigner);

        return jwt;
    }

    /**
     * 获取用户编号
     * @param token jwt票据
     * @return 用户编号
     */
    public static String getUserId(String token) {
        return decode(token).getPayloads().getStr(CommonConstants.ATTRIBUTE_NAME_USER_ID);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        secretKeyService = applicationContext.getBean(SecretKeyService.class);
    }
}
